'use strict';

const Service = require('egg').Service;
const fs = require('fs');

class NeedsService extends Service {

    /**
     * 创建model数据
     */
    async makeModel() {
        let resultObject = {
            code: 1,
            mag: '操作成功'
        }; //结果对象数据
        let data = []; //文件创建信息
        const modelPath = __dirname.replace('service', 'model');
        const {
            needs
        } = this.app.config;
        if (!fs.existsSync(modelPath)) {
            fs.mkdir(modelPath, function (err) {
                if (err) {
                    throw err;
                }
            });
        }
        //查询对应的表名及表结构
        this.app.mysql.select('information_schema.columns', {
            where: {
                table_schema: needs.database
            },
            columns: ['TABLE_NAME', 'COLUMN_NAME', 'CHARACTER_MAXIMUM_LENGTH', 'NUMERIC_PRECISION', 'NUMERIC_SCALE', 'DATA_TYPE', 'COLUMN_TYPE', 'COLUMN_KEY']
        }).then(result => {
            if (result !== null && result !== undefined) {
                //获取所有的表名集合
                let listTableName = [];
                for (let item of result) {
                    if (item["TABLE_NAME"] !== "SequelizeMeta")
                        listTableName.push(item["TABLE_NAME"]);
                }
                listTableName = [...new Set(listTableName)]; //数据去重操作
                console.log(listTableName)
                if (listTableName !== null && listTableName !== undefined && listTableName.length > 0) {
                    listTableName.forEach(tableName => {
                        let listGroupInfoForTable = result.filter(x => {
                            return x["TABLE_NAME"] === tableName;
                        })
                        if (listGroupInfoForTable !== null && listGroupInfoForTable !== undefined && listGroupInfoForTable.length > 0) {
                            //获取文件名
                            let fileName = tableName.substring(0, 1).toLowerCase() + tableName.substring(1);
                            //获取表对应的表结构，用于创建model数据
                            let sequelizeObj = {}; //Sequelize 对象数据
                            //获取对应表数据结构类型
                            let listDataType = [];
                            for (let item of listGroupInfoForTable) {
                                listDataType.push(item["DATA_TYPE"]);
                            }
                            listDataType = [...new Set(listDataType)]; //数据去重操作
                            //mysql对应的数据类型转换成Sequelize 数据类型
                            let listSequelizeDataType = [];
                            listDataType.forEach(dataType => {
                                switch (dataType.toLowerCase()) {
                                    case "varchar":
                                        listSequelizeDataType.push("STRING");
                                        break;
                                    case "text":
                                        listSequelizeDataType.push("TEXT");
                                        break;
                                    case "tinyint":
                                    case "int":
                                    case "integer":
                                        listSequelizeDataType.push("INTEGER");
                                        break;
                                    case "float":
                                        listSequelizeDataType.push("FLOAT");
                                        break;
                                    case "double":
                                        listSequelizeDataType.push("DOUBLE");
                                        break;
                                    case "bit":
                                        listSequelizeDataType.push("BOOLEAN");
                                        break;
                                    case "decimal":
                                        listSequelizeDataType.push("DECIMAL");
                                        break;
                                    case "date":
                                        listSequelizeDataType.push("DATEONLY");
                                        break;
                                    case "datetime":
                                        listSequelizeDataType.push("DATE");
                                        break;
                                }
                            })
                            listSequelizeDataType = [...new Set(listSequelizeDataType)]; //数据去重操作
                            let strDataType = listSequelizeDataType.join(',');

                            listGroupInfoForTable.forEach(tabItem => {
                                switch (tabItem["DATA_TYPE"].toLowerCase()) {
                                    case "varchar":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'STRING(' + parseInt(tabItem["CHARACTER_MAXIMUM_LENGTH"]) + ')'
                                        }
                                        break;
                                    case "text":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'TEXT'
                                        }
                                        break;
                                    case "tinyint":
                                    case "int":
                                    case "integer":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'INTEGER'
                                        }
                                        break;
                                    case "float":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'FLOAT'
                                        }
                                        break;
                                    case "double":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'DOUBLE'
                                        }
                                        break;
                                    case "bit":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'BOOLEAN'
                                        }
                                        break;
                                    case "decimal":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'DECIMAL(' + parseInt(tabItem["NUMERIC_PRECISION"]) + ',' + parseInt(tabItem["NUMERIC_SCALE"]) + ')'
                                        }
                                        break;
                                    case "date":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'DATEONLY'
                                        }
                                        break;
                                    case "datetime":
                                        sequelizeObj[tabItem["COLUMN_NAME"]] = {
                                            type: 'DATE'
                                        }
                                        break;
                                }
                                if (tabItem["COLUMN_KEY"].toLowerCase() === "pri") {
                                    sequelizeObj[tabItem["COLUMN_NAME"]].primaryKey = true;
                                }
                            })
                            let tableNameTemp = tableName.substring(0, 1).toUpperCase() + tableName.substring(1);
                            let modelObjTxt = JSON.stringify(sequelizeObj); //数据库模型对应的文本
                            modelObjTxt = modelObjTxt.replace(/"/g, '');
                            modelObjTxt = '{\n\t\t' + modelObjTxt.substring(1);
                            modelObjTxt = modelObjTxt.split('},').join('},\n\t\t');
                            let modelTxt = "'use strict';\n\n";
                            modelTxt += "module.exports = app => {\n";
                            modelTxt += "\tconst {" + strDataType + "}=app.Sequelize;\n\n";
                            modelTxt += "\tconst " + tableNameTemp + "=app.model.define('" + tableName + "'," + modelObjTxt + ");\n";
                            modelTxt += "\treturn " + tableNameTemp + ";\n};";

                            let dirName = "";
                            Object.keys(needs.databaseGrouping).forEach(keyName => {
                                needs.databaseGrouping[keyName].forEach(name => {
                                    if (name.toLowerCase() === tableName.toLowerCase()) {
                                        dirName = keyName;
                                    }
                                })
                            });
                            //为了避免重新创建发生覆盖操作，排除已创建
                            if (needs.noLongerCreate.indexOf(tableNameTemp) < 0) {
                                let filePath = modelPath+ "/" + fileName + ".js";
                                fs.writeFile(filePath, modelTxt, {
                                    flag: "w"
                                }, (err) => {
                                    if (err) {
                                        data.push({
                                            fileName: fileName,
                                            result: 'error',
                                            msg: err
                                        })
                                    } else {
                                        data.push({
                                            fileName: fileName,
                                            result: 'success',
                                            msg: 'write success'
                                        })
                                    }
                                });
                            }
                            resultObject.data = data;
                        }
                    })
                }
            }
        });
        return resultObject;
    };

    /**
     * 创建服务/控制类型数据
     * @param {*} type 操作类型 0=>service创建 1=>controller创建
     */
    async makeServiceOrController(type) {
        let resultObj = {
            code: 1,
            msg: '操作成功'
        }; //结果对象数据
        let data = []; //文件创建信息
        const {
            needs
        } = this.app.config;
        let filePathName = __dirname; //需要读取的文件路径
        let readFileName = ""; //需要读取的文件名称

        switch (type) {
            case 0: //service
                readFileName = filePathName + "/serviceBase.js";
                break;
            case 1: //controller
                filePathName = __dirname.replace('service', 'controller');
                readFileName = filePathName + "/controllerBase.js";
                break;
        }
        Object.keys(needs.databaseGrouping).forEach(keyName => {
            let tempPath = filePathName + "/" + keyName + "/";
            if (!fs.existsSync(tempPath)) {
                fs.mkdir(tempPath, function (err) {
                    if (err) {
                        throw err;
                    }
                });
            }
        });
        console.log(readFileName)
        this.readFile(readFileName).then(res => {
            this.app.mysql.select('information_schema.TABLES', {
                where: {
                    table_schema: needs.database
                },
                columns: ['TABLE_NAME']
            }).then(result => {
                if (result !== null && result !== undefined) {
                    result.forEach((item) => {
                        if (item["TABLE_NAME"] !== "SequelizeMeta") {
                            let tableName = item['TABLE_NAME'];
                            tableName = tableName.substring(0, 1).toLowerCase() + tableName.substring(1);
                            let dirName = ""; //文件目录
                            Object.keys(needs.databaseGrouping).forEach(keyName => {
                                needs.databaseGrouping[keyName].forEach(name => {
                                    if (name.toLowerCase() === tableName.toLowerCase()) {
                                        dirName = keyName;
                                    }
                                })
                            });
                            if (needs.noLongerCreate.indexOf(item['TABLE_NAME']) < 0) { //为了避免重新创建发生覆盖操作，排除已创建
                                let tableNameTemp = item['TABLE_NAME'].substring(0, 1).toUpperCase() + item['TABLE_NAME'].substring(1);
                                let readTxt = ""; //读取的文件内容
                                switch (type) {
                                    case 0: //service
                                        readTxt = res.replace(/BaseService/g, (tableNameTemp + "Service"));
                                        break;
                                    case 1: //controller
                                        readTxt = res.replace(/BaseController/g, (tableNameTemp + "Controller"));
                                        tableNameTemp = item['TABLE_NAME'].substring(0, 1).toLowerCase() + item['TABLE_NAME'].substring(1);
                                        break;
                                }
                                let changeModelName = ""; //需要替换的model对象
                                if (dirName.length > 0) {
                                    changeModelName = (dirName.substring(0, 1).toUpperCase() + dirName.substring(1)) + "." + tableNameTemp;
                                } else {
                                    changeModelName = tableNameTemp;
                                }
                                switch (type) {
                                    case 0: //service
                                        // changeModelName = changeModelName.substring(0, 1).toLowerCase() + changeModelName.substring(1);
                                        changeModelName=tableNameTemp;
                                        break;
                                    case 1: //controller
                                        changeModelName = changeModelName.substring(0, 1).toLowerCase() + changeModelName.substring(1);
                                        break;
                                }
                                readTxt = readTxt.replace(/Base/g, changeModelName);
                                readTxt = readTxt.replace(/ControllerAPI/g, changeModelName);
                                let filePath = filePathName + "/" + dirName + "/" + tableName + ".js";
                                fs.writeFile(filePath, readTxt, {
                                    flag: "w"
                                }, (err) => {
                                    if (err) {
                                        data.push({
                                            fileName: tableName,
                                            result: 'error',
                                            msg: err
                                        })
                                    } else {
                                        data.push({
                                            fileName: tableName,
                                            result: 'success',
                                            msg: 'write success'
                                        })
                                    }
                                });
                                resultObj.data = data;
                            }
                        }
                    });
                }
            });

        }).catch(err => {
            resultObj.msg = err;
            resultObj.code = 0;
        })
        return resultObj;
    };

    /**
     * 读取文件内容
     * @param {*} filePath 文件路径
     */
    readFile(filePath) {
        return new Promise((resolve, reject) => {
            fs.readFile(filePath, 'utf-8', (err, data) => {
                if (err) {
                    reject(err.toString())
                } else {
                    resolve(data.toString())
                }
            })
        })
    }
}
module.exports = NeedsService;
